package xyz.xtt.asset.service.impl;

import static xyz.xtt.common.asset.AssertUtils.isFalse;

import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Objects;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.yulichang.toolkit.JoinWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.google.common.collect.Lists;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import lombok.extern.slf4j.Slf4j;
import xyz.xtt.asset.client.response.AssetExtInfoResponse;
import xyz.xtt.asset.constants.AssetCache;
import xyz.xtt.asset.constants.ErrorMessage;
import xyz.xtt.asset.entity.TblAssetExt;
import xyz.xtt.asset.entity.TblAssetTransaction;
import xyz.xtt.asset.mapper.TblAssetExtMapper;
import xyz.xtt.asset.request.OperateUpRequest;
import xyz.xtt.asset.service.ITblAssetExtService;
import xyz.xtt.asset.service.ITblAssetTransactionService;
import xyz.xtt.asset.vo.PreSellInfoVo;
import xyz.xtt.common.starter.cache.CacheManager;

/**
 * <p>
 * 资产扩展信息表 服务实现类
 * </p>
 *
 * @author author
 * @since 2024-10-17
 */
@Slf4j
@Service
public class TblAssetExtServiceImpl extends ServiceImpl<TblAssetExtMapper, TblAssetExt> implements ITblAssetExtService {
	@Autowired
	private CacheManager cacheManager;
	@Autowired
	private ITblAssetTransactionService iTblAssetTransactionService;

	@Override
	public TblAssetExt info(Long assetId) {
		LambdaQueryChainWrapper<TblAssetExt> query = new LambdaQueryChainWrapper<>(baseMapper);
		return query.eq(TblAssetExt::getAssetId, assetId).one();
	}

	@Override
	public List<TblAssetExt> infoWithAssetIds(Collection<Long> assetIds) {
		if (CollectionUtil.isEmpty(assetIds)) {
			return Lists.newArrayList();
		}
		LambdaQueryChainWrapper<TblAssetExt> query = new LambdaQueryChainWrapper<>(baseMapper);
		return query.in(TblAssetExt::getAssetId, assetIds).list();
	}

	@Override
	public TblAssetExt infoWithAssetIdByCache(Long assetId) {
		return cacheManager.cacheObj(() -> info(assetId), AssetCache.TBL_ASSET_EXT, String.valueOf(assetId));
	}

	@Override
	public boolean putOnc2c(PreSellInfoVo preSellInfoVo, Long assetId) {
//		Long preStart = preSellInfoVo.getPreStart();
//		Long preEnd = preSellInfoVo.getPreEnd();
		LambdaUpdateChainWrapper<TblAssetExt> update = new LambdaUpdateChainWrapper<>(baseMapper);
		long currentTimeMillis = System.currentTimeMillis();
		boolean result = update
				.eq(TblAssetExt::getAssetId, assetId)
				.set(TblAssetExt::getPreSellStartDatetime, currentTimeMillis)
				.set(TblAssetExt::getSellStartDatetime, currentTimeMillis)
				.set(TblAssetExt::getLastModifyDatetime, currentTimeMillis)
				.update();
		return result;
	}

	@Override
	public boolean updatePutOn(PreSellInfoVo preSellInfoVo, long noticePeriodMinutes, TblAssetExt assetExt, OperateUpRequest operateUpRequest) {
		Long publicityPeriodStart = assetExt.getPublicityPeriodStart();
		Long publicityPeriodEnd = assetExt.getPublicityPeriodEnd();
		boolean checkPublicityPeriodEnd = assetExt.checkPublicityPeriodEnd();
		Long preStart = preSellInfoVo.getPreStart();
		Long preEnd = preSellInfoVo.getPreEnd();
		if (checkPublicityPeriodEnd) {
			// 已经完整公示，中间没有下架操作，不更新公示期
			publicityPeriodStart = assetExt.getPublicityPeriodStart();
			publicityPeriodEnd = assetExt.getPublicityPeriodEnd();
		} else {
			Date date = DateUtil.date();
			Date beginOfDay = DateUtil.beginOfDay(date);
			// 实际会多算一天
			Date newDate = DateUtil.offset(beginOfDay, DateField.DAY_OF_MONTH, 14);
			Date endOfDay = DateUtil.endOfDay(newDate);

			publicityPeriodStart = DateUtil.toInstant(beginOfDay).toEpochMilli();
			publicityPeriodEnd = DateUtil.toInstant(endOfDay).toEpochMilli();
			// 保存存操作记录使用赋值
			assetExt.setPublicityPeriodStart(publicityPeriodStart);
			assetExt.setPublicityPeriodEnd(publicityPeriodEnd);
			// 检查预售期，如果设置了，必须比公示期结束的时间大
			isFalse(operateUpRequest.checkPresell(publicityPeriodEnd, preStart, preEnd), ErrorMessage.CHECK_PRE_SELL_EX, () -> log
					.info("updatePutOn checkPresell ex assetId:{}", assetExt.getAssetId()));

		}
		LambdaUpdateChainWrapper<TblAssetExt> update = new LambdaUpdateChainWrapper<>(baseMapper);
		boolean result = update
				.eq(TblAssetExt::getAssetId, assetExt.getAssetId())
				.set(TblAssetExt::getPublicityPeriodStart, publicityPeriodStart)
				.set(TblAssetExt::getPublicityPeriodEnd, publicityPeriodEnd)
				.set(TblAssetExt::getPreSellStartDatetime, preStart)
				.set(TblAssetExt::getSellStartDatetime, preEnd)
				.set(TblAssetExt::getLastModifyDatetime, System.currentTimeMillis())
				.set(TblAssetExt::getLastPutOnSaleDatetime, System.currentTimeMillis())
				.update();
		return result;
	}

	@Override
	public boolean updatePutOff(Long assetId) {
		long curr = System.currentTimeMillis();
		LambdaUpdateChainWrapper<TblAssetExt> update = new LambdaUpdateChainWrapper<>(baseMapper);
		return update
				.eq(TblAssetExt::getAssetId, assetId)
				.set(TblAssetExt::getPublicityPeriodStart, 0)
				.set(TblAssetExt::getPublicityPeriodEnd, 0)
				.lt(TblAssetExt::getPublicityPeriodStart, curr)
				.ge(TblAssetExt::getPublicityPeriodEnd, curr)
				.update();
	}

	@Override
	public List<AssetExtInfoResponse> queryBatchAssetExtInfoResponse(Collection<Long> assetIds) {
		MPJLambdaWrapper<TblAssetExt> query = JoinWrappers.lambda(TblAssetExt.class).in(TblAssetExt::getAssetId, assetIds);
		List<AssetExtInfoResponse> list = query.list(AssetExtInfoResponse.class);
		return list;
	}

	@Override
	public AssetExtInfoResponse queryAssetExtInfoResponseInfo(Long assetId) {
		MPJLambdaWrapper<TblAssetExt> query = JoinWrappers.lambda(TblAssetExt.class).eq(TblAssetExt::getAssetId, assetId);
		AssetExtInfoResponse one = query.one(AssetExtInfoResponse.class);
		return one;
	}

	@Override
	public Boolean saveUpChainFlag(String appUid, Long businessRefId) {
		TblAssetTransaction transaction = iTblAssetTransactionService.queryPaySyncOne(appUid, businessRefId);
		if (Objects.isNull(transaction)) {
			return Boolean.FALSE;
		}
		LambdaUpdateChainWrapper<TblAssetExt> update = new LambdaUpdateChainWrapper<>(baseMapper);
		boolean result = update
				.eq(TblAssetExt::getAssetId, transaction.getAssetId())
				.set(TblAssetExt::getUpChain, 1)
				.set(TblAssetExt::getLastModifyDatetime, System.currentTimeMillis())
				.update();
		// 清除缓存
		if (Objects.equals(Boolean.TRUE, result)) {
			cacheManager.delete(AssetCache.TBL_ASSET_EXT, String.valueOf(transaction.getAssetId()));
		}
		return result;
	}
}
